package com.wt.springsamples.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.wt.springsamples.interceptor.AccessLogInterceptor;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
import org.springframework.http.CacheControl;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.resource.VersionResourceResolver;
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;

import java.time.Duration;
import java.util.List;

/**
 * 实现WebMvcConfigurer可实现自定已配置，如添加拦截器，过滤器等
 * 原理：@EnableWebMvc注解导入DelegatingWebMvcConfiguration配置类，并会将所有实现WebMvcConfigurer接口的类已List的方式进行注入
 * SpringBoot原理：WebMvcAutoConfiguration自动配置类的内部类EnableWebMvcConfiguration继承了DelegatingWebMvcConfiguration，因此也能实现WebMvcConfigurer集合的注入
 */
@Configuration
//@EnableAutoConfiguration(exclude = ErrorMvcAutoConfiguration.class)
//@EnableWebMvc  //官网实例中使用了该注解，该注解其实为一个复合注解，默认开启了mvc的核心组件，使用springboot后不需要配置
public class MvcConfig implements WebMvcConfigurer {

    /**
     * 必须配置已解决日期类型参数问题
     * 或者在@Controller、@ControllerAdvice注解的类中添加方法：
     *     @InitBinder
     *     public void initBinder(WebDataBinder binder) {
     *         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
     *         dateFormat.setLenient(false);
     *         binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
     *     }
     *
     * @param registry
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
        registrar.setUseIsoFormat(true);
        registrar.registerFormatters(registry);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("forward:/index.html");
    }

//    @Override
//    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
//
//        ObjectMapper objectMapper = new ObjectMapper();
//        /**
//         * 序列换成json时,将所有的long变成string
//         * 因为js中得数字类型不能包含所有的java long值
//         */
//        SimpleModule simpleModule = new SimpleModule();
//        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
//        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
//        objectMapper.registerModule(simpleModule);
//        jackson2HttpMessageConverter.setObjectMapper(objectMapper);
//        converters.add(jackson2HttpMessageConverter);
//    }

    /**
     * 添加拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(new LocaleChangeInterceptor());
        registry.addInterceptor(new AccessLogInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
    }

    /**
     * 跨域配置，方式1
     * 使用spring security后会失效
     * @param registry
     */
//    @Override
//    public void addCorsMappings(CorsRegistry registry) {
//        registry.addMapping("/**")
//                .allowedOrigins("127.0.0.1:8081")
//                .allowedOriginPatterns("*")
//                //设置了allowCredentials为true后使用该配置会报错
//                .allowedOrigins("*")
//                .allowedMethods("*")
//                .allowedHeaders("*")
//                .exposedHeaders("*")
//                .allowCredentials(true)//设置跨域cookie等信息
//                .maxAge(3600);
//    }

    /**
     * 跨域配置,方式2
     * 使用spring security后需要配置其顺序小于-100
     */
//    @Bean
//    FilterRegistrationBean<CorsFilter> corsFilter(){
//        FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();
//        CorsConfiguration corsConfiguration = new CorsConfiguration();
//        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
//        corsConfiguration.setAllowedMethods(Arrays.asList("*"));
//        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));
//        corsConfiguration.setMaxAge(3600L);
//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        source.registerCorsConfiguration("/**",corsConfiguration);
//        registrationBean.setFilter(new CorsFilter(source));
//        registrationBean.setOrder(-101);
//        return registrationBean;
//    }

    /**
     * reactive
     * @return
     */
//    @Bean
//    public CorsWebFilter corsWebFilter(){
//        org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource corsConfigurationSource = new org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource();
//        CorsConfiguration corsConfiguration = new CorsConfiguration();
//        corsConfiguration.setAllowCredentials(true);
//        corsConfiguration.addAllowedOrigin("*");
//        corsConfiguration.addAllowedHeader("*");
//        corsConfiguration.addAllowedMethod("*");
//        corsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
//        return new CorsWebFilter(corsConfigurationSource);
//    }
}
